﻿using System;
using System.Collections.Generic;
using System.Linq;

using Sumen.Business.Presenter.Actor;
using Sumen.Library.Enum;
using Sumen.Model.Model;

namespace Sumen.Business.Presenter.Inventory
{
    public class InventoryPresenter
    {

        /// <summary>
        /// Get all list inventory
        /// </summary>
        /// <returns></returns>
        public ICollection<inventory> GetAllInventories()
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                
                return objEntities.inventories.ToList();
                
            }
        }

        /// <summary>
        /// Get all product exist in inventory
        /// </summary>
        /// <param name="pId"></param>
        /// <returns></returns>
        public ICollection<object> GetAllExist(string pStockID)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                

                var list = objEntities.inventories.Where(p => p.Inv_Quantity > 0).ToList();
                string show = ClsPublic.SYSTEM_DISPLAY_ACTIVED;
                var listProduct = (from p in objEntities.product_details where show == "1" ? p.product.Prod_Actived != null : p.product.Prod_Actived == 1 select p).ToList();
                var query = from p in list
                            where p.Inv_Stock_ID == pStockID
                            join pp in listProduct
                            on p.Inv_PRODUCT_DETAILS_ID equals pp.Prods_ID into Inners
                            from inner in Inners.DefaultIfEmpty()
                            select new
                            {
                                p.Inv_ID,
                                p.Inv_PRODUCT_DETAILS_ID,
                                p.Inv_Product_Name,
                                inner.product.Prod_Product_ID,
                                p.Inv_Quantity,
                                p.Inv_Amount,
                                Posx_Code_X = p.position_x_inventory == null ? null : p.position_x_inventory.Posx_Code_X,
                                Posx_ID = p.position_x_inventory == null ? (int?)null : p.position_x_inventory.Posx_ID,
                                Inv_Cost = (p.Inv_Amount / p.Inv_Quantity) + p.Inv_Ship,
                                PriceBasic = p.Inv_Amount / p.Inv_Quantity,
                                p.Inv_Sale_Price,
                                p.Inv_Retails_Price,
                                p.Inv_Agent_Price
                            };
                return new[] { query.ToList() };
            }
        }

        /// <summary>
        /// Get inventory by Stock ID
        /// </summary>
        /// <param name="pValue"></param>
        /// <returns></returns>
        public ICollection<object> GetByKey(object pValue)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                

                string stockId = pValue + string.Empty;
                var list = from p in objEntities.inventories
                           where p.Inv_Quantity > 0 && (stockId != "" ? p.Inv_Stock_ID == stockId : p.Inv_Stock_ID != null)
                           select new
                           {
                               p.Inv_Amount,
                               p.Inv_Quantity,
                               p.Inv_RefDate,
                               p.product_details.Prods_ID,
                               p.product_details.product.Prod_Product_ID,
                               p.product_details.product.Prod_Product_Name,
                               p.position_x_inventory.Posx_Code_X,
                               p.product_details.product_size.Size_Name,
                               p.product_details.product_color.Color_Name,
                               p.product_details.product.product_type.Prodt_Name,
                               p.product_details.product.category.Cat_Title,
                               Inv_Price = p.Inv_Amount / p.Inv_Quantity,
                               p.stock.stock_name,
                               Inv_Ship = p.Inv_Ship + (p.Inv_Amount / p.Inv_Quantity),
                               p.product_details.product
                           };
                ProductPresenter productPresenter = new ProductPresenter();
                var query = from p in list.AsEnumerable()
                    select new
                    {
                        p.Inv_Amount,
                        p.Inv_Quantity,
                        p.Inv_RefDate,
                        p.Prods_ID,
                        p.Prod_Product_ID,
                        p.Prod_Product_Name,
                        p.Posx_Code_X,
                        p.Size_Name,
                        p.Color_Name,
                        p.Prodt_Name,
                        p.Cat_Title,
                        p.Inv_Price,
                        p.stock_name,
                        p.Inv_Ship,
                        Picture = productPresenter.GetPicture(productPresenter.UrlDesImage,p.product.Prod_Product_ID, p.product.Prod_Image)
                    };
                return new[] { query.ToList() };
            }
        }

        /// <summary>
        /// Get list inventory by product details id
        /// </summary>
        /// <param name="pvalue"></param>
        /// <returns></returns>
        public ICollection<inventory> GetByProductDetailsId(object pvalue)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                string productDetailsId = pvalue.ToString();
                var query = (from p in objEntities.inventories where p.Inv_PRODUCT_DETAILS_ID == productDetailsId select p).ToList();
                foreach (var inventories in query)
                {
                    objEntities.Entry(inventories).Reference(p => p.product_details).Load();
                    objEntities.Entry(inventories.product_details).Reference(p => p.product).Load();
                    objEntities.Entry(inventories.product_details).Reference(p => p.product_color).Load();
                    objEntities.Entry(inventories.product_details).Reference(p => p.product_size).Load();
                }
                return query;
            }
        }

        public ICollection<object> GetGeneralInventory(string pStockID, DateTime pBegin, DateTime pEnd)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                int Inward = (int)EnumRefType.Inward;
                int Outward = (int)EnumRefType.Outward;
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                var queryInwardBegin = from p in objEntities.inventory_details
                                       where p.Invd_RefType == Inward && p.Invd_RefDate < pBegin && (pStockID != "" ? p.Invd_Stock_ID == pStockID : p.Invd_Stock_ID != null)
                                       group p by new
                                       {
                                           p.product_details.product.Prod_Product_ID,
                                           p.product_details.product.Prod_Product_Name,
                                           p.product_details.product.product_type.Prodt_Name,
                                           p.product_details.product.category.Cat_Title
                                       }
                                           into Grouped
                                           select new
                                           {
                                               Invd_PRODUCT_DETAILS_ID = Grouped.Key.Prod_Product_ID,
                                               Invd_Quantity = Grouped.Sum(p1 => p1.Invd_Quantity),
                                               Invd_Amount = Grouped.Sum(p2 => p2.Invd_Amount),
                                               Grouped.Key.Prod_Product_Name,
                                               Grouped.Key.Prodt_Name,
                                               Grouped.Key.Cat_Title
                                           };
                var queryOutwardBegin = from p in objEntities.inventory_details
                                        where p.Invd_RefType == Outward && p.Invd_RefDate < pBegin && (pStockID != "" ? p.Invd_Stock_ID == pStockID : p.Invd_Stock_ID != null)
                                        group p by new
                                        {
                                            p.product_details.product.Prod_Product_ID,
                                            p.product_details.product.Prod_Product_Name,
                                            p.product_details.product.product_type.Prodt_Name,
                                            p.product_details.product.category.Cat_Title
                                        }
                                            into Grouped
                                            select new
                                            {
                                                Invd_PRODUCT_DETAILS_ID = Grouped.Key.Prod_Product_ID,
                                                Invd_Quantity = Grouped.Sum(p => p.Invd_Quantity),
                                                Invd_Amount = Grouped.Sum(p => p.Invd_Amount),
                                                Grouped.Key.Prod_Product_Name,
                                                Grouped.Key.Prodt_Name,
                                                Grouped.Key.Cat_Title
                                            };
                var queryInward = from p in objEntities.inventory_details
                                  where p.Invd_RefType == Inward && (p.Invd_RefDate >= pBegin && p.Invd_RefDate <= pEnd) && (pStockID != "" ? p.Invd_Stock_ID == pStockID : p.Invd_Stock_ID != null)
                                  group p by new
                                  {
                                      p.product_details.product.Prod_Product_ID,
                                      p.product_details.product.Prod_Product_Name,
                                      p.product_details.product.product_type.Prodt_Name,
                                      p.product_details.product.category.Cat_Title
                                  }
                                      into Grouped
                                      select new
                                      {
                                          Invd_PRODUCT_DETAILS_ID = Grouped.Key.Prod_Product_ID,
                                          Invd_Quantity = Grouped.Sum(p1 => p1.Invd_Quantity),
                                          Invd_Amount = Grouped.Sum(p2 => p2.Invd_Amount),
                                          Grouped.Key.Prod_Product_Name,
                                          Grouped.Key.Prodt_Name,
                                          Grouped.Key.Cat_Title
                                      };
                var queryOutward = from p in objEntities.inventory_details
                                   where p.Invd_RefType == Outward && (p.Invd_RefDate >= pBegin && p.Invd_RefDate <= pEnd) && (pStockID != "" ? p.Invd_Stock_ID == pStockID : p.Invd_Stock_ID != null)
                                   group p by new
                                   {
                                       p.product_details.product.Prod_Product_ID,
                                       p.product_details.product.Prod_Product_Name,
                                       p.product_details.product.product_type.Prodt_Name,
                                       p.product_details.product.category.Cat_Title
                                   }
                                       into Grouped
                                       select new
                                       {
                                           Invd_PRODUCT_DETAILS_ID = Grouped.Key.Prod_Product_ID,
                                           Invd_Quantity = Grouped.Sum(p => p.Invd_Quantity),
                                           Invd_Amount = Grouped.Sum(p => p.Invd_Amount),
                                           Grouped.Key.Prod_Product_Name,
                                           Grouped.Key.Prodt_Name,
                                           Grouped.Key.Cat_Title
                                       };
                var query = from p in queryInward
                            join p1 in queryOutward on p.Invd_PRODUCT_DETAILS_ID equals p1.Invd_PRODUCT_DETAILS_ID into Inners
                            from inner in Inners.DefaultIfEmpty()
                            join p2 in queryInwardBegin on p.Invd_PRODUCT_DETAILS_ID equals p2.Invd_PRODUCT_DETAILS_ID into Inners1
                            from inner1 in Inners1.DefaultIfEmpty()
                            join p3 in queryOutwardBegin on p.Invd_PRODUCT_DETAILS_ID equals p3.Invd_PRODUCT_DETAILS_ID into Inners2
                            from inner2 in Inners2.DefaultIfEmpty()
                            select new
                            {
                                p.Prod_Product_Name,
                                Prod_Product_ID = p.Invd_PRODUCT_DETAILS_ID,
                                p.Cat_Title,
                                p.Prodt_Name,
                                Begin_Quantity = inner1.Invd_Quantity ?? 0 - inner2.Invd_Quantity ?? 0,
                                Begin_Amount = inner1.Invd_Amount ?? 0 - inner2.Invd_Amount ?? 0,
                                Inward_Quantity = p.Invd_Quantity ?? 0,
                                Inward_Amount = p.Invd_Amount ?? 0,
                                Outward_Amount = inner.Invd_Amount ?? 0,
                                Outward_Quantity = inner.Invd_Quantity ?? 0,
                                Inventory_Quantity = (p.Invd_Quantity ?? 0) + (inner1.Invd_Quantity ?? 0 - inner2.Invd_Quantity ?? 0) - (inner.Invd_Quantity ?? 0),
                                Inventory_Amount = (p.Invd_Amount ?? 0) + (inner1.Invd_Amount ?? 0 - inner2.Invd_Amount ?? 0) - (inner.Invd_Amount ?? 0)
                            };
                //var list = (from p in query.AsEnumerable() select p).ToList();
                return new[] { query.ToList() };
            }
        }


        /// <summary>
        /// Load all inventory details (Product History) by category
        /// </summary>
        /// <returns></returns>
        public ICollection<object> GetHistoryProduct(List<object> pCatId, DateTime dateBegin,DateTime dateEnd)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                var query = (from p in objEntities.inventory_details
                             where p.Invd_RefDate >= dateBegin && p.Invd_RefDate <= dateEnd
                                 
                             join p1 in objEntities.stocks on p.Invd_Stock_ID equals p1.stock_id into Inners
                             from inner in Inners.DefaultIfEmpty()
                             select new
                             {
                                 p.Invd_RefDate,
                                 p.Invd_RefNo,
                                 Invd_RefType = p.Invd_RefType == 1 ? "Nhập kho" : p.Invd_RefType == 2 ? "Xuất kho" : "Bán hàng",
                                 p.product_details.product.Prod_Product_ID,
                                 p.product_details.Prods_ID,
                                 p.product_details.product.Prod_Product_Name,
                                 p.product_details.product_color.Color_Name,
                                 p.product_details.product_size.Size_Name,
                                 p.product_details.product.category.Cat_Title,
                                 p.product_details.product.product_type.Prodt_Name,
                                 p.Invd_Quantity,
                                 p.Invd_Price,
                                 p.Invd_Amount,
                                 p.Invd_Stock_ID,
                                 p.Invd_UnitPrice,
                                 inner.stock_name,
                                 p.position_x_inventory.Posx_Code_X,
                                 p.product_details.product.Prod_CATEGORY_ID
                             }).ToList();
                var result =
                    query.Where(
                        c => pCatId != null ? pCatId.Contains((int) c.Prod_CATEGORY_ID) : c.Prod_CATEGORY_ID != null);
                return new[] { result };
            }
        }

        public ICollection<object> GetInwardOutward(string pStockId, DateTime pBegin, DateTime pEnd)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                var queryInward = from p in objEntities.stock_inward
                                  where (!string.IsNullOrEmpty(pStockId) ? p.Inw_Stock_id == pStockId : p.Inw_Stock_id != null) && (p.Inw_RefDate >= pBegin && p.Inw_RefDate <= pEnd)
                                  join s in objEntities.stocks on p.Inw_Stock_id equals s.stock_id into Inners
                                  from inner in Inners.DefaultIfEmpty()
                                  select new
                                  {
                                      Date = p.Inw_RefDate,
                                      Code = p.Inw_ID,
                                      BusinessName = p.Inw_RefType == (int)(object)EnumRefType.Inward ? "Nhập kho" : p.Inw_RefType == (int)(object)EnumRefType.Outward ? "Xuất kho" : "Bán hàng",
                                      Stock = inner.stock_name,
                                      CustomerName = p.Inw_Provider_Name,
                                      Address = p.Inw_Provider_Address,
                                      Contact = p.Inw_Provider_Contact,
                                      Payment = p.Inw_Payment,
                                      VAT = p.Inw_VAT,
                                      Discount = (decimal?)0,
                                      RefType = p.Inw_RefType,
                                      Amount = p.Inw_Amount
                                  };
                var queryOutward = from p in objEntities.stock_outward
                                   where (!string.IsNullOrEmpty(pStockId) ? p.Outw_Stock_id == pStockId : p.Outw_Stock_id != null) && (p.Outw_RefDate >= pBegin && p.Outw_RefDate <= pEnd)
                                   join s in objEntities.stocks on p.Outw_Stock_id equals s.stock_id into Inners
                                   from inner in Inners.DefaultIfEmpty()
                                   select new
                                   {
                                       Date = p.Outw_RefDate,
                                       Code = p.Outw_ID,
                                       BusinessName = p.Outw_RefType == (int)(object)EnumRefType.Inward ? "Nhập kho" : p.Outw_RefType == (int)(object)EnumRefType.Outward ?"Xuất kho" : "Bán hàng",
                                       Stock = inner.stock_name,
                                       CustomerName = p.Outw_Customer_Name,
                                       Address = p.Outw_Customer_Address,
                                       Contact = p.Outw_Customer_Contact,
                                       Payment = p.Outw_Payment,
                                       VAT = (int?)0,
                                       Discount = p.Outw_Discount,
                                       RefType = p.Outw_RefType,
                                       Amount = p.Outw_Amount
                                   };
                var query = queryInward.Union(queryOutward);
                return query.ToArray();
            }
        }

        public ICollection<object> GetInwardDetails(string pInwardId)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                var query = from p1 in objEntities.stock_inward_details
                            where p1.Inws_STOCK_INWARD_ID == pInwardId
                            join pos in objEntities.position_x_inventory on p1.Inws_POSITION_X_ID equals pos.Posx_ID into InnerPos
                            from innerPos in InnerPos.DefaultIfEmpty()
                            select new
                            {
                                ProductID = p1.Inws_PRODUCT_DETAILS_ID,
                                ProductName = p1.Inws_Product_Name,
                                ProductColor = p1.product_details.product_color.Color_Name,
                                ProductSize = p1.product_details.product_size.Size_Name,
                                Cat = p1.product_details.product.category.Cat_Title,
                                Price = p1.Inws_UnitPrice,
                                Quantity = p1.Inws_Quantity,
                                Amount = p1.Inws_Amount,
                                Position = innerPos.Posx_Code_X
                            };
                return query.ToArray();
            }
        }

        public ICollection<object> GetOutwardDetails(string pOutwardId)
        {
            using (sumenEntities objEntities = new sumenEntities())
            {
                objEntities.Configuration.LazyLoadingEnabled = false;
                objEntities.Configuration.ProxyCreationEnabled = false;
                var query = from p1 in objEntities.stock_outward_details
                            where p1.Outws_STOCK_OUTWARD_ID == pOutwardId
                            join pos in objEntities.position_x_inventory on p1.Outws_POSITION_X_ID equals pos.Posx_ID into InnerPos
                            from innerPos in InnerPos.DefaultIfEmpty()
                            select new
                            {
                                ProductID = p1.Outws_PRODUCT_Details_ID,
                                ProductName = p1.Outws_ProductName,
                                ProductColor = p1.product_details.product_color.Color_Name,
                                ProductSize = p1.product_details.product_size.Size_Name,
                                Cat = p1.product_details.product.category.Cat_Title,
                                Price = p1.Outws_UnitPrice,
                                Quantity = p1.Outws_Quantity,
                                Amount = p1.Outws_Amount,
                                Position = innerPos.Posx_Code_X
                            };
                return query.ToArray();
            }
        }


        /// <summary>
        /// Get quantity by product Details id in stock
        /// </summary>
        /// <param name="pProductDetailsId"></param>
        /// <returns></returns>
        public int GetQuantityByProductDetailsId(string pProductDetailsId)
        {
            using (sumenEntities objSumenEntities = new sumenEntities())
            {
                //var query = objSumenEntities.inventories.GroupBy(p=>p.Inv_PRODUCT_DETAILS_ID
                int quantity = (from p in objSumenEntities.inventories
                    where p.Inv_PRODUCT_DETAILS_ID == pProductDetailsId
                    select p).Sum(p => p.Inv_Quantity) ?? 0;

                return quantity;
            }
        }

    }
}
